import CryptoJS from 'crypto-js';
import {
	JSEncrypt
} from 'jsencrypt';

// RSA+AES 加密
export const RsaAesEncrypt = (
	publicKey,
	plaintext,
	aesIv = '0000000000000000',
	keySize = 128,
	aesMode = CryptoJS.mode.CBC,
	aesPadding = CryptoJS.pad.Pkcs7,
	en = CryptoJS.enc.Utf8,
) => {
	if (keySize < 128) {
		console.log('KeySize cannot be less than 128.');
		return;
	}
	// 生成 AES 密钥和初始化向量
	let aesKey = CryptoJS.lib.WordArray.random(keySize / 8).toString();
	plaintext = plaintext.toString(en);
	// 使用 AES 加密明文
	let ciphertext = AesEncrypt(
		aesKey,
		plaintext,
		aesIv,
		aesMode,
		aesPadding,
		en,
	);

	// 使用 RSA 公钥加密 AES 密钥
	let rsaEncryptor = new JSEncrypt();
	rsaEncryptor.setPublicKey(publicKey);
	let encryptedAesKey = rsaEncryptor.encrypt(aesKey.toString());

	// 返回加密后的密文和加密后的 AES 密钥
	return {
		data: ciphertext.toString(),
		key: encryptedAesKey,
	};
};

// RSA+AES 解密
export const RsaAesDecrypt = (
	privateKey,
	encryptedAesKey,
	ciphertext,
	aesIv = '0000000000000000',
	aesMode = CryptoJS.mode.CBC,
	aesPadding = CryptoJS.pad.Pkcs7,
	en = CryptoJS.enc.Utf8,
) => {
	// 使用RSA私钥解密AES密钥
	let rsaDecryptor = new JSEncrypt();
	rsaDecryptor.setPrivateKey(privateKey);
	let aesKey = rsaDecryptor.decrypt(encryptedAesKey);
	// 使用AES解密密文
	let decryptedPlaintext = AesDecrypt(
		aesKey,
		ciphertext,
		aesIv,
		aesMode,
		aesPadding,
		en,
	);
	// 返回解密后的明文
	return decryptedPlaintext.toString(en);
};

//AES 加密
export const AesEncrypt = (
	aesKey,
	textData,
	aesIv = '0000000000000000',
	aesMode = CryptoJS.mode.CBC,
	aesPadding = CryptoJS.pad.Pkcs7,
	en = CryptoJS.enc.Utf8,
) => {
	let key = en.parse(aesKey);
	let iv = en.parse(aesIv);
	let text = en.parse(textData);
	let encrypted = CryptoJS.AES.encrypt(text, key, {
		iv: iv,
		mode: aesMode,
		padding: aesPadding,
	});
	return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
};

//AES 解密
export const AesDecrypt = (
	aesKey,
	base64,
	aesIv = '0000000000000000',
	aesMode = CryptoJS.mode.CBC,
	aesPadding = CryptoJS.pad.Pkcs7,
	en = CryptoJS.enc.Utf8,
) => {
	let key = en.parse(aesKey);
	let iv = en.parse(aesIv);
	let encrypted = CryptoJS.AES.decrypt(base64, key, {
		iv: iv,
		mode: aesMode,
		padding: aesPadding,
	});
	return encrypted.toString(en);
};